<?php
// +----------------------------------------------------------------------
// | KungfuCMS [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016 http://www.0ya0.com All rights reserved.
// +----------------------------------------------------------------------
// | Author: 三藏 <dungang@126.com> <http://www.0ya0.com>
// +----------------------------------------------------------------------

defined('BASEPATH') OR exit('No direct script access allowed');

class Installer {

    public $install_path;
    public $ci;

    public function __construct(){
        $this->install_path = dirname(APPPATH).'/';
        $this->ci =& get_instance();
    }

    public function check_environment(){

        $items = array(
            'os'      => array(lang('os'), lang('no_limited'), lang('like_unix'), PHP_OS, 'success'),
            'php'     => array(lang('php_version'), '5.2', '5.2+', PHP_VERSION, 'success'),
            'upload'  => array(lang('upload_file_size'), lang('no_limited'), '2M+', lang('unknown'), 'success'),
            'gd'      => array(lang('gd_lib'), '2.0', '2.0+', lang('unknown'), 'success'),
            'disk'    => array(lang('disk_space'), '5M', lang('no_limited'), lang('unknown'), 'success'),
        );


        //PHP环境检测
        if($items['php'][3] < $items['php'][1]){
            $items['php'][4] = 'danger';
            $_SESSION['error'] = 'environment';
        }

        //附件上传检测
        if(@ini_get('file_uploads'))
            $items['upload'][3] = ini_get('upload_max_filesize');

        //GD库检测
        $tmp = function_exists('gd_info') ? gd_info() : array();
        if(empty($tmp['GD Version'])){
            $items['gd'][3] = lang('uninstalled');
            $items['gd'][4] = 'danger';
            $_SESSION['error'] = 'environment';
        } else {
            $items['gd'][3] = $tmp['GD Version'];
        }
        unset($tmp);

        //磁盘空间检测
        if(function_exists('disk_free_space')) {
            $items['disk'][3] = floor(disk_free_space($this->install_path) / (1024*1024)).'M';
        }

        return $items;
    }

    public function check_dirs_and_files(){
        $items = array(
            array('dir',  lang('writable'), 'success', './uploads/download'),
            array('dir',  lang('writable'), 'success', './uploads/picture'),
            array('dir',  lang('writable'), 'success', './uploads/editor'),
            array('dir',  lang('writable'), 'success', './addons/',''),
            array('dir',  lang('writable'), 'success', './application/cache',''),
            array('file', lang('writable'), 'success', './application/config/config.php'),
            array('file', lang('writable'), 'success', './application/config/database.php'),

        );

        foreach ($items as &$val) {
            if('dir' == $val[0]){
                if(!is_writable($this->install_path . $val[3])) {
                    if(is_dir($this->install_path . $val[3])) {
                        $val[1] = lang('readable');
                        $val[2] = 'danger';
                        $_SESSION['error'] = 'environment';
                    } else {
                        $val[1] = lang('not_existed');
                        $val[2] = 'danger';
                        $_SESSION['error'] = 'environment';
                    }
                }
            } else {
                if(file_exists($this->install_path . $val[3])) {
                    if(!is_writable($this->install_path . $val[3])) {
                        $val[1] = lang('not_writable');
                        $val[2] = 'danger';
                        $_SESSION['error'] = 'environment';
                    }
                } else {
                    if(!is_writable(dirname($this->install_path . $val[3]))) {
                        $val[1] = lang('not_existed');
                        $val[2] = 'danger';
                        $_SESSION['error'] = 'environment';
                    }
                }
            }
        }

        if (empty($_SESSION['error'])){
            $_SESSION['dir_writable'] = TRUE;
        } else {
            unset($_SESSION['dir_writable']);
        }

        return $items;
    }


    /**
     * 函数检测
     * @return array 检测数据
     */
    public function check_functions(){
        $items = array(
            array('mysql_connect',     lang('support'), 'success'),
            array('file_get_contents', lang('support'), 'success'),
            array('mb_strlen',		   lang('support'), 'success'),
        );

        foreach ($items as &$val) {
            if(!function_exists($val[0])){
                $val[1] = lang('unsupported');
                $val[2] = 'danger';
                $val[3] = lang('on');
                $_SESSION['error'] = 'environment';
            }
        }

        return $items;
    }


    /**
     * 写入配置文件
     * @param  array $settings 配置信息
     * @param string $auth
     * @return array
     */
    public function write_config($settings, $auth){
        if(is_array($settings)){
            //读取配置内容
            $config = file_get_contents(APPPATH . 'data/config.tpl');
            $database = file_get_contents(APPPATH . 'data/database.tpl');
            //替换配置项
            foreach ($settings as $name => $value) {
                $config = str_replace("[{$name}]", $value, $config);
                $database = str_replace("[{$name}]", $value, $database);
            }

            $conf = str_replace('[encryption_key]', $auth, $config);
            $app_name = config_item('app_name') ? config_item('app_name') : 'application';
            //写入应用配置文件
            if(empty($_SESSION['dir_writable'])){
                $this->show_msg(lang('app_writable_dirs_and_files_not_writable'),"danger");
                $this->show_msg(realpath($this->install_path).$app_name."/config/config.php","danger");
                $this->show_msg(realpath($this->install_path).$app_name."/config/database.php","danger");
                $_SESSION['error'] = 'setting';
            }else{
                if(file_put_contents($this->install_path .$app_name. '/config/config.php', $conf) &&
                    file_put_contents($this->install_path .$app_name. '/config/database.php',$database)
                ){
                    $this->show_msg(lang('config_file_wrote_success'));
                } else {
                    $this->show_msg(lang('config_file_wrote_failure'), 'danger');
                    $_SESSION['error'] = 'setting';
                }
            }

        }
    }

    /**
     * 创建数据表
     * @param  string $db_name 数据库名称
     * @param string $prefix
     */
    public function create_tables($db_name, $prefix = ''){
        $db = $this->ci->db;
        //开始安装
        $this->show_msg(lang('installing_database') . '...');
        if ($db->conn_id){
            $sql = "CREATE DATABASE IF NOT EXISTS `{$db_name}` DEFAULT CHARACTER SET utf8";
            if(!$db->query($sql)){
                $this->show_msg( lang('create_database') . ":{$db_name}...".lang('failure'), 'danger');
            } else {
                $db->db_select($db_name);
                $this->show_msg( lang('create_database') . ":{$db_name}...".lang('success'));
            }
        } else {
            $this->show_msg( lang('connect_database') . ":{$db_name}...".lang('failure'), 'danger');
        }

        //读取SQL文件
        $sql = file_get_contents(APPPATH . 'data/install.sql');
        $sql = str_replace("\r", "\n", $sql);
        $sql = explode(";\n", $sql);

        //替换表前缀
        $original = config_item('original_tab_prefix');
        $sql = str_replace(" `{$original}", " `{$prefix}", $sql);
        foreach ($sql as $value) {
            $value = trim($value);
            if(empty($value)) continue;
            if(substr($value, 0, 12) == 'CREATE TABLE') {
                $name = preg_replace("/^CREATE TABLE `(\w+)` .*/s", "\\1", $value);
                $msg  = lang('create_table') . "{$name}";
                if(false !== $db->query($value)){
                    $this->show_msg($msg . '...' . lang('success'),'success');
                } else {
                    $this->show_msg($msg . '...'. lang('failure'), 'danger');
                    $_SESSION['error']='setting';
                }
            } else {
                $db->query($value);
            }

        }
    }


    public function register_administrator($prefix, $admin,$auth){
        $db = $this->ci->db;
        $this->show_msg(lang('start_creating_creator') . '...');
        $password = $this->user_md5($admin['password'], $auth);
        $sql = "INSERT INTO `[PREFIX]member` VALUES ".
            "('1', '[NAME]', '[PASS]', '[EMAIL]', '','[NAME]', '0', '0000-00-00', '', '0', '1', '[IP]', '[TIME]', '0', '[TIME]', '1');";
        $sql = str_replace(
            array('[PREFIX]', '[NAME]', '[PASS]', '[EMAIL]', '[NAME]', '[IP]','[TIME]'),
            array($prefix, $admin['user'], $password, $admin['email'],$admin['user'],$this->get_client_ip(1),time()),
            $sql);
        $db->query($sql);
        $this->show_msg(lang('creator_register_completed'));
    }

    /**
     * 生成系统AUTH_KEY
     * @author 麦当苗儿 <zuojiazi@vip.qq.com>
     */
    public function build_auth_key(){
        $chars  = 'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
        $chars .= '`~!@#$%^&*()_+-=[]{};:"|,.<>/?';
        $chars  = str_shuffle($chars);
        return substr($chars, 0, 40);
    }

    /**
     * 系统非常规MD5加密方法
     * @param  string $str 要加密的字符串
     * @param  string $key
     * @return string
     */
    public function user_md5($str, $key = ''){
        return '' === $str ? '' : md5(sha1($str) . $key);
    }

    /**
     * 及时显示提示信息
     * @param  string $msg 提示信息
     * @param string $class
     */
    public function show_msg($msg, $class = 'success'){
        echo ("<script type=\"text/javascript\">show_msg(\"{$msg}\", \"{$class}\")</script>");

    }

    public function get_client_ip($type = 0) {
        $type       =  $type ? 1 : 0;
        static $ip  =   NULL;
        if ($ip !== NULL) return $ip[$type];
        $ip = $this->ci->input->ip_address();
        // IP地址合法验证
        $long = sprintf("%u",ip2long($ip));
        $ip   = $long ? array($ip, $long) : array('0.0.0.0', 0);
        return $ip[$type];
    }
}